﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Reflection;
using System.IO;
using System.Windows.Markup;
using System.Collections.ObjectModel;

namespace GestaltDesigner
{
    public partial class Page : UserControl
    {
        Collection<string> _names;
        double _top, _left = 10.0;
        Dictionary<string, string> _controlEvents;
        public PropertyGridDataObject propertyGridDataObject = new PropertyGridDataObject();

        public Page()
        {
            InitializeComponent();
            InitializeControlTypes();
            _names = new Collection<string>();
            this.KeyDown += new KeyEventHandler(Page_KeyDown);
            //karstenj -- this is a bit of a hammer because I'm taking over the entire datacontext for
            //the purpose of the property grid. If someone needs the global datacontext for the app then
            //they'll have to refactor this

            //also we have to use the dispatcher begininvoke to get around silverlight databinding bugs
            //see: http://blogs.imeta.co.uk/aboyne/archive/2009/02/10/603.aspx 
            Dispatcher.BeginInvoke(() => this.DataContext = propertyGridDataObject);
            propertyGridDataObject.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(propertyGridDataObject_PropertyChanged);
        }

        void propertyGridDataObject_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            //if width or height got changed we have to update the design surface's SelectionUI to match the side
            if (e.PropertyName == "Width" || e.PropertyName == "Height" || e.PropertyName == "Top" || e.PropertyName == "Left")
            {
                _designSurface.UpdateSelectionUI();
            }
            //we need to modify the property grid depending on the type of control
            if (e.PropertyName == "BackingControl")
            {
                //contentcontrol
                if (propertyGridDataObject.BackingControl is ContentControl)
                    _propertyGrid.stackPanelContent.Visibility = Visibility.Visible;
                else
                    _propertyGrid.stackPanelContent.Visibility = Visibility.Collapsed;
                //textbox or textblock
                if  (propertyGridDataObject.BackingControl is TextBox || propertyGridDataObject.BackingControl is TextBlock)
                    _propertyGrid.stackPanelText.Visibility = Visibility.Visible;
                else
                    _propertyGrid.stackPanelText.Visibility = Visibility.Collapsed;
                //imagesource
                if (propertyGridDataObject.BackingControl is Image)
               
                    _propertyGrid.stackPanelImage.Visibility = Visibility.Visible;
                else
                    _propertyGrid.stackPanelImage.Visibility = Visibility.Collapsed;

                if (propertyGridDataObject.BackingControl is MediaElement)
                    _propertyGrid.stackPanelMedia.Visibility = Visibility.Visible;
                else
                    _propertyGrid.stackPanelMedia.Visibility = Visibility.Collapsed;

                if (propertyGridDataObject.BackingControl is MultiScaleImage)
                    _propertyGrid.stackPanelDeepZoom.Visibility = Visibility.Visible;
                else
                    _propertyGrid.stackPanelDeepZoom.Visibility = Visibility.Collapsed; 

                }


        }


        void Page_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Delete)
            {
                _names.Remove(_designSurface.SelectedElement.Name);
                _designSurface.RemoveControl(_designSurface.SelectedElement);
                _designSurface.SelectedElement = null;
            }
        }

        private void InitializeControlTypes()
        {
            Dictionary<string, string> controlTypes = new Dictionary<string, string>();
            StreamReader reader = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("GestaltDesigner.InitParams.txt"));
            string entry;
            string[] keyValuePair;
            while (!reader.EndOfStream)
            {
                entry = reader.ReadLine();
                keyValuePair = entry.Split(',');
                controlTypes.Add(keyValuePair[0], keyValuePair[1]);
            }

            ToolBoxCategory controlCategory = new ToolBoxCategory("Controls", controlTypes);
            _toolBox.Categories.Add(controlCategory);

            _toolBox.ItemChosen += new EventHandler<ToolBoxItemChosenEventArgs>(toolBox_ItemChosen);

            //containterTypes.Add (typeof(System.Windows.Controls.Border));
            //containterTypes.Add (typeof(System.Windows.Controls.Canvas));
            //containterTypes.Add (typeof(System.Windows.Controls.Grid));
            //containterTypes.Add (typeof(System.Windows.Controls.InkPresenter));
            //containterTypes.Add (typeof(System.Windows.Controls.Panel));
            //containterTypes.Add (typeof(System.Windows.Controls.ScrollViewer));
            //containterTypes.Add (typeof(System.Windows.Controls.StackPanel));

            //dialogTypes.Add (typeof(System.Windows.Controls.OpenFileDialog));

            _controlEvents = new Dictionary<string, string>();
            reader = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("GestaltDesigner.DefaultHandlers.txt"));
            while (!reader.EndOfStream)
            {
                entry = reader.ReadLine();
                keyValuePair = entry.Split(',');
                _controlEvents.Add(keyValuePair[0], keyValuePair[1]);
            }
        }

        string GenerateUniqueName(string typeName)
        {
            int i = 1;
            while (_names.Contains(typeName + i.ToString()))
            {
                i++;
            }
            return typeName + i.ToString();
        }

        void toolBox_ItemChosen(object sender, ToolBoxItemChosenEventArgs e)
        {

            string name = GenerateUniqueName(e.Name);
            string xaml = e.Type.Replace("%d", name);
            _top += 10.0;
            _left += 10.0;
            FrameworkElement control = XamlReader.Load(xaml) as FrameworkElement;
            control.SetValue(Canvas.TopProperty, _top);
            control.SetValue(Canvas.LeftProperty, _left);
            _designSurface.AddControl(control);


            _names.Add(name);
        }


        private void _designSurface_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.NewSelection == null)
                _propertyGrid.stackPanelPropertyGrid.Visibility = Visibility.Collapsed;
            else
            {
                _propertyGrid.stackPanelPropertyGrid.Visibility = Visibility.Visible;
                propertyGridDataObject.BackingControl = e.NewSelection;

            }
            //need to put in placeholder borders for non-selected media elements, images and multiscale images
            //first blow away all the rectangles
            //can't use foreach because of InvalidOperationException
            for (int i = 0; i < this._designSurface._designSurfaceRoot.Children.Count; i++)
            {
                try
                {
                    FrameworkElement fe = this._designSurface._designSurfaceRoot.Children[i] as FrameworkElement;
                    if (fe is Rectangle)
                        this._designSurface._designSurfaceRoot.Children.RemoveAt(i);
                }
                catch (InvalidCastException)
                { }

            }
            //then add them back but not to this one
            for (int i = 0; i < this._designSurface._designSurfaceRoot.Children.Count; i++)
            {
                try
                {
                    FrameworkElement fe = this._designSurface._designSurfaceRoot.Children[i] as FrameworkElement;
                    if (e.NewSelection != null)
                        if (fe.Name != ((FrameworkElement)(e.NewSelection)).Name)
                        {
                            if (fe is MediaElement || fe is Image || fe is MultiScaleImage)
                            {
                                string name = GenerateUniqueName("Rectangle");
                                _names.Add(name);

                                Rectangle rectangle = new Rectangle();

                                rectangle.Name = name;
                                rectangle.SetValue(Canvas.TopProperty, fe.GetValue(Canvas.TopProperty));
                                rectangle.SetValue(Canvas.LeftProperty, fe.GetValue(Canvas.LeftProperty));
                                rectangle.Width = fe.Width;
                                rectangle.Height = fe.Height;
                                rectangle.Fill = new SolidColorBrush(Colors.Gray);
                                rectangle.Opacity = .5;
                                this._designSurface._designSurfaceRoot.Children.Add(rectangle);
                            }
                        }
              

                }
                catch (InvalidCastException)
                { }

            }

           

        }
    }
}
